home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 September / CHIP Eylül 1998.iso / Slackwar / docs / Virtual-Services-HOWTO < prev    next >
Text File  |  1997-11-14  |  29KB  |  943 lines

  1.   Virtual Services Howto
  2.   Brian Ackerman, brian@nycrc.net
  3.   v1.2, 4 November 1997
  4.  
  5.   This document came about to satisfy the ever increasing need to know
  6.   how to virtualize a service.
  7.  
  8.   1.  Introduction
  9.  
  10.   1.1.  Knowledge Required
  11.  
  12.   Creating a virtual services machine is not all that difficult.
  13.   However, more than fundamental knowledge is required.  And this
  14.   document is not a primer to how to fully configure a Linux machine.
  15.  
  16.   In order to understand this HOWTO document it is assumed that you are
  17.   thoroughly familiar with the following:
  18.  
  19.   ╖  Compiling a Linux kernel and adding IP aliasing support IP alias
  20.      mini-HOWTO
  21.  
  22.   ╖  Setting up and configuring of network devices NET-3 HOWTO
  23.  
  24.   ╖  Setting up of inetd NET-3 HOWTO
  25.  
  26.   ╖  Compiling and installing various network packages like Sendmail
  27.      Site Apache Site Wu-Ftpd FAQ
  28.  
  29.   ╖  Setting up DNS DNS HOWTO
  30.  
  31.   If you are uncertain of how to proceed with any of the above it is
  32.   STRONGLY recommended that you use the links provided to familiarize
  33.   yourself with all packages.  I will NOT reply to any mail reguarding
  34.   any of the above.  Please direct any questions to the appropriate
  35.   author of the HOWTO.
  36.  
  37.   1.2.  Purpose
  38.  
  39.   The purpose of virtual services is to allow a single machine to
  40.   recognize multiple IP addresses without multiple network cards.  IP
  41.   aliasing is a kernel option that allows you to assign each network
  42.   device more than one IP address.  The kernel then multiplexes (swaps
  43.   between them very fast) in the background and to the user it appears
  44.   like you have more than one network card.
  45.  
  46.   This multiplexing allows multiple domains (www.domain1.com,
  47.   www.domain2.com, etc.) to be hosted by the same machine for the same
  48.   cost as hosting one domain.  Unfortunately, most services (ftp, web,
  49.   mail) were not designed to handle muliple domains.  In order to make
  50.   them work properly you must modify both configuration files and source
  51.   code.  This document describes how to make these modifications in the
  52.   setting up of a virtual machine.
  53.  
  54.   A deamon is also required in order to make virtual services function.
  55.   The source for this daemon (virtuald) is provided later in this
  56.   document.
  57.  
  58.   1.3.  Feedback
  59.  
  60.   This document will expand as packages are updated and source or
  61.   configuration modifications change.   If there are any portions of
  62.   this document that are unclear please feel free to email me with your
  63.   suggestions or questions.  So that I do not have to go searching
  64.   through the entire HOWTO please make certain that all comments are as
  65.   specific as possible and include the section where the uncertainty
  66.   lies.  It is important that all mail be addressed with VIRTSERVICES
  67.   HOWTO in the subject line.  Any other mail will be considered personal
  68.   and all my friends know that I do not ever read my personal mail so it
  69.   will probably get discarded with theirs.
  70.  
  71.   Please note that my examples are just that, examples and should not be
  72.   copied verbatim.   You may have to insert your own values.   If you
  73.   are having trouble, send me mail, with all the pertinent configuration
  74.   files and the error messages you get when installing, and I will look
  75.   them over and mail my suggestions back.
  76.  
  77.   1.4.  Revision History
  78.  
  79.   V1.0 Initial version
  80.  
  81.   V1.1 Fixed error in Virtual Web Section
  82.  
  83.   V1.2 Fixed the date
  84.  
  85.   1.5.  Copyright/Distribution
  86.  
  87.   This document is Copyright (c) 1997 by The Computer Resource Center
  88.   Inc.
  89.  
  90.   A verbatim copy may be reproduced or distributed in any medium
  91.   physical or electronic without permission of the author.  Translations
  92.   are similiarly permitted without express permission if it includes a
  93.   notice on who translated it.  Commercial redistribution is allowed and
  94.   encouraged; however please notify Computer Resource Center of any such
  95.   distributions.
  96.  
  97.   Excerpts from the document may be used without prior consent provided
  98.   that the derivative work contains the verbatim copy or a pointer to a
  99.   verbatim copy.
  100.  
  101.   Permission is granted to make and distribute verbatim copies of this
  102.   document provided the copyright notice and this permission notice are
  103.   preserved on all copies.
  104.  
  105.   In short, we wish to promote dissemination of this information through
  106.   as many channels as possible. However, I do wish to retain copyright
  107.   on this HOWTO document, and would like to be notified of any plans to
  108.   redistribute this HOWTO.
  109.  
  110.   2.  IP aliasing
  111.  
  112.   IP aliasing is a kernel option that needs to be set up in order to run
  113.   a virtual hosting machine.  There is already a mini-HOWTO on IP
  114.   aliasing.  Consult that for any questions on how to set it up.
  115.  
  116.   3.  Virtuald
  117.  
  118.   3.1.  How it works
  119.  
  120.   Every network connection is made up of two IP address/port pairs.  The
  121.   API (Applications Program Interface) for network programming is called
  122.   the Sockets API.  The socket acts like an open file and by
  123.   reading/writing to it you can send data over a network connection.
  124.   There is a function call  getsockname  that will return the IP address
  125.   of the local socket.  Virtuald uses  getsockname to determine which IP
  126.   on the local machine is being accessed.  Virtuald reads a config file
  127.   to retrieve the directory associated with that IP.  It will
  128.    chroot  to that directory and hand the connection off to the service.
  129.   Chroot  resets / or the root directory to a new point so everything
  130.   higher in the directory tree is cut off from the running program.
  131.   Therefore, each IP address gets their own virtual filesystem.   To the
  132.   network program this is transparent and the program will behave like
  133.   nothing happened.  Virtuald in conjunction with a program like inetd
  134.   can then be used to virtualize any service.
  135.  
  136.   3.2.  inetd
  137.  
  138.   Inetd is a network super server that listens at multiple ports and
  139.   when it receives a connection (for example, an incoming pop request),
  140.   inetd performs the network negotiation and hands the network
  141.   connection off to the specified program.  This prevents servers from
  142.   running idly when they are not needed.
  143.  
  144.   A standard /etc/inetd.conf file looks like this:
  145.  
  146.   ftp stream tcp nowait root /usr/sbin/tcpd wu.ftpd -l -a
  147.   pop-3 stream tcp nowait root /usr/sbin/tcpd in.qpop -s
  148.  
  149.   A virtual /etc/inetd.conf file looks like this:
  150.  
  151.   ftp stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.ftp wu.ftpd -l -a
  152.   pop-3 stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.pop in.qpop -s
  153.  
  154.   3.3.  virtual.conf
  155.  
  156.   Each service gets a conf file that will control what IPs and
  157.   directories are allowed for that service.  You can have one master
  158.   conf file or several conf files if you want each service to get a
  159.   different list of domains.   A virtual.conf file looks like this:
  160.  
  161.   # This is a comment and so are blank lines
  162.  
  163.   # Format IP <SPACE> dir <NOSPACES>
  164.   10.10.10.129 /virtual/foo.bar.com
  165.   10.10.10.130 /virtual/bar.foo.com
  166.   10.10.10.157 /virtual/boo.la.com
  167.  
  168.   3.4.  The source (virtuald)
  169.  
  170.   #include <netinet/in.h>
  171.   #include <sys/socket.h>
  172.   #include <arpa/inet.h>
  173.   #include <stdarg.h>
  174.   #include <string.h>
  175.   #include <syslog.h>
  176.   #include <stdio.h>
  177.  
  178.   #define BUFSIZE 8192
  179.  
  180.   main(int argc,char **argv)
  181.   {
  182.           char buffer[BUFSIZE];
  183.           char *ipaddr,*dir;
  184.  
  185.           logit("Virtuald Starting: $Revision: 1.21 $");
  186.           if (!argv[1])
  187.           {
  188.                   logit("invalid arguments: no conf file");
  189.                   quitting_virtuald(0);
  190.           }
  191.           if (!argv[2])
  192.           {
  193.                   logit("invalid arguments: no program to run");
  194.                   quitting_virtuald(0);
  195.           }
  196.           if (getipaddr(&ipaddr))
  197.           {
  198.                   logit("getipaddr failed");
  199.                   quitting_virtuald(0);
  200.           }
  201.           sprintf(buffer,"Incoming ip: %s",ipaddr);
  202.           logit(buffer);
  203.           if (iptodir(&dir,ipaddr,argv[1]))
  204.           {
  205.                   logit("iptodir failed");
  206.                   quitting_virtuald(0);
  207.           }
  208.           if (chroot(dir)<0)
  209.           {
  210.                   logit("chroot failed: %m");
  211.                   quitting_virtuald(0);
  212.           }
  213.           sprintf(buffer,"Chroot dir: %s",dir);
  214.           logit(buffer);
  215.           if (chdir("/")<0)
  216.           {
  217.                   logit("chdir failed: %m");
  218.                   quitting_virtuald(0);
  219.           }
  220.           if (execvp(argv[2],argv+2)<0)
  221.           {
  222.                   logit("execvp failed: %m");
  223.                   quitting_virtuald(0);
  224.           }
  225.   }
  226.  
  227.   int logit(char *buf)
  228.   {
  229.           openlog("virtuald",LOG_PID,LOG_DAEMON);
  230.           syslog(LOG_ERR,buf);
  231.           closelog();
  232.           return 0;
  233.   }
  234.  
  235.   int quitting_virtuald(int retval)
  236.   {
  237.           exit(retval);
  238.           return 0;
  239.   }
  240.  
  241.   int getipaddr(char **ipaddr)
  242.   {
  243.           struct sockaddr_in virtual_addr;
  244.           static char ipaddrbuf[BUFSIZE];
  245.           int virtual_len;
  246.           char *ipptr;
  247.  
  248.           virtual_len=sizeof(virtual_addr);
  249.           if (getsockname(0,(struct sockaddr *)&virtual_addr,&virtual_len)<0)
  250.           {
  251.                   logit("getipaddr: getsockname failed: %m");
  252.                   return -1;
  253.           }
  254.           if (!(ipptr=inet_ntoa(virtual_addr.sin_addr)))
  255.           {
  256.                   logit("getipaddr: inet_ntoa failed: %m");
  257.                   return -1;
  258.           }
  259.           strncpy(ipaddrbuf,ipptr,sizeof(ipaddrbuf)-1);
  260.           *ipaddr=ipaddrbuf;
  261.           return 0;
  262.   }
  263.  
  264.   int iptodir(char **dir,char *ipaddr,char *filename)
  265.   {
  266.           char buffer[BUFSIZE],*bufptr;
  267.           static char dirbuf[BUFSIZE];
  268.           FILE *fp;
  269.  
  270.           if (!(fp=fopen(filename,"r")))
  271.           {
  272.                   logit("iptodir: fopen failed: %m");
  273.                   return -1;
  274.           }
  275.           *dir=NULL;
  276.           while(fgets(buffer,BUFSIZE,fp))
  277.           {
  278.                   buffer[strlen(buffer)-1]=0;
  279.                   if (*buffer=='#' || *buffer==0)
  280.                           continue;
  281.                   if (!(bufptr=strchr(buffer,' ')))
  282.                   {
  283.                           logit("iptodir: strchr failed");
  284.                           return -1;
  285.                   }
  286.                   *bufptr++=0;
  287.                   if (!strcmp(buffer,ipaddr))
  288.                   {
  289.                           strncpy(dirbuf,bufptr,sizeof(dirbuf)-1);
  290.                           *dir=dirbuf;
  291.                           break;
  292.                   }
  293.           }
  294.           if (fclose(fp)==EOF)
  295.           {
  296.                   logit("iptodir: fclose failed: %m");
  297.                   return -1;
  298.           }
  299.           if (!*dir)
  300.           {
  301.                   logit("iptodir: ip not found in conf file");
  302.                   return -1;
  303.           }
  304.           return 0;
  305.   }
  306.  
  307.   4.  Virt scripts
  308.  
  309.   4.1.  virtfs
  310.  
  311.   Each domain should get their own directory structure.  Since you are
  312.   using  chroot  you will require duplicate copies of the shared
  313.   libraries, binaries, conf files, etc.  I use /virtual/domain.com for
  314.   each domain that I create.  I realize that you are taking up more disk
  315.   space but it is cheaper than a whole new machine and network cards.
  316.   If you really want to preserve space you can link the files together
  317.   so only one copy of each binary exists.
  318.  
  319.   Here is a sample virtfs script:
  320.  
  321.   #!/bin/bash
  322.  
  323.   echo '$Revision: 1.21 $'
  324.  
  325.   echo -n "Enter the domain name: "
  326.   read domain
  327.  
  328.   if [ "$domain" = "" ]
  329.   then
  330.           echo Nothing entered: aborting
  331.           exit 0
  332.   fi
  333.  
  334.   leadingdir=/virtual
  335.  
  336.   echo -n "Enter leading dir: (Enter for default: $leadingdir): "
  337.   read ans
  338.  
  339.   if [ "$ans" != "" ]
  340.   then
  341.           leadingdir=$ans
  342.   fi
  343.  
  344.   newdir=$leadingdir/$domain
  345.  
  346.   if [ -d "$newdir" ]
  347.   then
  348.           echo New directory: $newdir: ALREADY exists
  349.           exit 0
  350.   else
  351.           echo New directory: $newdir
  352.   fi
  353.  
  354.   echo Create $newdir
  355.   mkdir -p $newdir
  356.  
  357.   echo Create bin
  358.   cp -pdR /bin $newdir
  359.  
  360.   echo Create dev
  361.   cp -pdR /dev $newdir
  362.  
  363.   echo Create dev/log
  364.   ln -f /virtual/log $newdir/dev/log
  365.  
  366.   echo Create etc
  367.   mkdir -p $newdir/etc
  368.   for i in /etc/*
  369.   do
  370.           if [ -d "$i" ]
  371.           then
  372.                   continue
  373.           fi
  374.           cp -pd $i $newdir/etc
  375.   done
  376.  
  377.   echo Create etc/skel
  378.   mkdir -p $newdir/etc/skel
  379.  
  380.   echo Create home
  381.   for i in a b c d e f g h i j k l m n o p q r s t u v w x y z
  382.   do
  383.           mkdir -p $newdir/home/$i
  384.   done
  385.  
  386.   echo Create home/c/crc
  387.   mkdir -p $newdir/home/c/crc
  388.   chown crc.users $newdir/home/c/crc
  389.  
  390.   echo Create lib
  391.   mkdir -p $newdir/lib
  392.   for i in /lib/*
  393.   do
  394.           if [ -d "$i" ]
  395.           then
  396.                   continue
  397.           fi
  398.           cp -pd $i $newdir/lib
  399.   done
  400.  
  401.   echo Create proc
  402.   mkdir -p $newdir/proc
  403.  
  404.   echo Create sbin
  405.   cp -pdR /sbin $newdir
  406.  
  407.   echo Create tmp
  408.   mkdir -p -m 0777 $newdir/tmp
  409.   chmod +t $newdir/tmp
  410.  
  411.   echo Create usr
  412.   mkdir -p $newdir/usr
  413.  
  414.   echo Create usr/bin
  415.   cp -pdR /usr/bin $newdir/usr
  416.  
  417.   echo Create usr/lib
  418.   mkdir -p $newdir/usr/lib
  419.  
  420.   echo Create usr/lib/locale
  421.   cp -pdR /usr/lib/locale $newdir/usr/lib
  422.  
  423.   echo Create usr/lib/terminfo
  424.   cp -pdR /usr/lib/terminfo $newdir/usr/lib
  425.  
  426.   echo Create usr/lib/zoneinfo
  427.   cp -pdR /usr/lib/zoneinfo $newdir/usr/lib
  428.  
  429.   echo Create usr/lib/\*.so\*
  430.   cp -pdR /usr/lib/*.so* $newdir/usr/lib
  431.  
  432.   echo Create usr/sbin
  433.   cp -pdR /usr/sbin $newdir/usr
  434.  
  435.   echo Linking usr/tmp
  436.   ln -s /tmp $newdir/usr/tmp
  437.  
  438.   echo Create var
  439.   mkdir -p $newdir/var
  440.  
  441.   echo Create var/lock
  442.   cp -pdR /var/lock $newdir/var
  443.  
  444.   echo Create var/log
  445.   mkdir -p $newdir/var/log
  446.  
  447.   echo Create var/log/wtmp
  448.   cp /dev/null $newdir/var/log/wtmp
  449.  
  450.   echo Create var/run
  451.   cp -pdR /var/run $newdir/var
  452.  
  453.   echo Create var/run/utmp
  454.   cp /dev/null $newdir/var/run/utmp
  455.  
  456.   echo Create var/spool
  457.   cp -pdR /var/spool $newdir/var
  458.  
  459.   echo Linking var/tmp
  460.   ln -s /tmp $newdir/var/tmp
  461.  
  462.   echo Create var/www/html
  463.   mkdir -p $newdir/var/www/html
  464.   chown webmast.www $newdir/var/www/html
  465.   chmod g+s $newdir/var/www/html
  466.  
  467.   echo Create var/www/master
  468.   mkdir -p $newdir/var/www/master
  469.   chown webmast.www $newdir/var/www/master
  470.  
  471.   echo Create var/www/server
  472.   mkdir -p $newdir/var/www/server
  473.   chown webmast.www $newdir/var/www/server
  474.  
  475.   exit 0
  476.  
  477.   4.2.  virtexec
  478.  
  479.   To execute commands in a virtual environment you have to
  480.    chroot  to that directory and then run the command.  I have written a
  481.   special shell script called virtexec that handles this for any
  482.   command:
  483.  
  484.   #!/bin/sh
  485.  
  486.   echo '$Revision: 1.21 $'
  487.  
  488.   BNAME=`basename $0`
  489.   FIRST4CHAR=`echo $BNAME | cut -c1-4`
  490.   REALBNAME=`echo $BNAME | cut -c5-`
  491.  
  492.   if [ "$BNAME" = "virtexec" ]
  493.   then
  494.           echo Cannot run virtexec directly: NEED a symlink
  495.           exit 0
  496.   fi
  497.  
  498.   if [ "$FIRST4CHAR" != "virt" ]
  499.   then
  500.           echo Symlink not a virt function
  501.           exit 0
  502.   fi
  503.  
  504.   list=""
  505.   num=1
  506.   for i in /virtual/*
  507.   do
  508.           if [ ! -d "$i" ]
  509.           then
  510.                   continue
  511.           fi
  512.           if [ "$i" = "/virtual/lost+found" ]
  513.           then
  514.                   continue
  515.           fi
  516.           list="$list $i $num"
  517.           num=`expr $num + 1`
  518.   done
  519.  
  520.   if [ "$list" = "" ]
  521.   then
  522.           echo No virtual environments exist
  523.           exit 0
  524.   fi
  525.  
  526.   dialog --clear --title 'Virtexec' --menu Pick 20 70 12 $list 2> /tmp/menu.$$
  527.   if [ "$?" = "0" ]
  528.   then
  529.           newdir=`cat /tmp/menu.$$`
  530.   else
  531.           newdir=""
  532.   fi
  533.   tput clear
  534.   rm -f /tmp/menu.$$
  535.  
  536.   echo '$Revision: 1.21 $'
  537.  
  538.   if [ ! -d "$newdir" ]
  539.   then
  540.           echo New directory: $newdir: NOT EXIST
  541.           exit 0
  542.   else
  543.           echo New directory: $newdir
  544.   fi
  545.  
  546.   echo bname: $BNAME
  547.  
  548.   echo realbname: $REALBNAME
  549.  
  550.   if [ "$*" = "" ]
  551.   then
  552.           echo args: none
  553.   else
  554.           echo args: $*
  555.   fi
  556.  
  557.   echo Changing to $newdir
  558.   cd $newdir
  559.  
  560.   echo Running program $REALBNAME
  561.  
  562.   chroot $newdir $REALBNAME $*
  563.  
  564.   exit 0
  565.  
  566.   Please note that you must have the  dialog  program installed on your
  567.   system for this to work.  To use virtexec just symlink a program to
  568.   it.  For example,
  569.  
  570.   ln -s /usr/bin/virtexec /usr/bin/virtpasswd
  571.   ln -s /usr/bin/virtexec /usr/bin/virtvi
  572.   ln -s /usr/bin/virtexec /usr/bin/virtpico
  573.   ln -s /usr/bin/virtexec /usr/bin/virtemacs
  574.   ln -s /usr/bin/virtexec /usr/bin/virtmailq
  575.  
  576.   Then if you type virtvi or virtpasswd or virtmailq it will allow you
  577.   to vi a program, change a user's password or check the mail queue on
  578.   your virtual system.  You can create as many virtexec symlinks as you
  579.   want.  However, note that if your program requires a shared library it
  580.   has to be in the virtual filesystem.  The binary has to exist on the
  581.   virtual filesystem also.
  582.  
  583.   4.3.  Notes on virtfs and virtexec
  584.  
  585.   I install all the scripts in /usr/bin.  Anything that I do not want to
  586.   put on the virtual filesystem I put in /usr/local.  The script does
  587.   not touch anything in there for copying.  Any files that are important
  588.   to not cross virtual filesystems should be removed.  For example, ssh
  589.   is installed on my system and I did not want the private key for the
  590.   server available on all the virtual filesystems so I remove it from
  591.   each virtual filesystem after I run virtfs.  I also change resolv.conf
  592.   and remove anything that has the name of another domain on it for
  593.   legal reasons.  For example, /etc/hosts and /etc/HOSTNAME.
  594.  
  595.   The programs that I symlink to virtexec are:
  596.  
  597.   ╖  virtpasswd -- change a user password
  598.  
  599.   ╖  virtadduser -- create a user
  600.  
  601.   ╖  virtdeluser -- delete a user
  602.  
  603.   ╖  virtsmbstatus -- see samba status
  604.  
  605.   ╖  virtvi -- edit a file
  606.  
  607.   ╖  virtmailq -- check out the mailq
  608.  
  609.   ╖  virtnewaliases -- rebuild alias tables
  610.  
  611.   5.  DNS
  612.  
  613.   You can configure DNS normally.  The beauty of this system is that all
  614.   services will behave normally like they are on separate machines.
  615.   There is a HOWTO on DNS.
  616.  
  617.   6.  Syslog
  618.  
  619.   6.1.  Problem
  620.  
  621.   Syslog is the system logging utility commonly used on UNIX systems.
  622.   Syslog is a daemon that opens a special file called a FIFO.  A FIFO is
  623.   a special file that is like a pipe.  Anything that is written to the
  624.   write side will come out the read side.  The syslog daemon waits for
  625.   data from the read side.  There are C functions that write to the
  626.   write side.  If you write your program with these C functions your
  627.   output will go to syslog.  Remember that we have used a
  628.    chroot  environment and the FIFO /dev/log is not in the virtual
  629.   environment.  That means all the virtual environments will not log to
  630.   syslog.  We cannot simply copy the file since the programs use
  631.   /dev/log instead of the new one we would create.
  632.  
  633.   Beware that certain versions of syslog use a udp socket instead of the
  634.   FIFO.  However, this is usually not the case.
  635.  
  636.   6.2.  Solution
  637.  
  638.   Syslog can look to a different FIFO if you tell it on the command line
  639.   so run syslog with the argument:
  640.  
  641.   syslog -p /virtual/log
  642.  
  643.   Then link /dev/log to /virtual/log by (Note it is a SYMLINK):
  644.  
  645.   ln -sf /virtual/log /dev/log
  646.  
  647.   Then link all the /dev/log copies to this file by running (Note it is
  648.   a hard link and NOT a symlink):
  649.  
  650.   ln /virtual/log /virtual/domain.com/dev/log
  651.  
  652.   The virtfs script above already does this.  Since /virtual is one
  653.   contiguous disk and the /dev/log's are linked they have the same inode
  654.   number and point to the same data.  The  chroot  cannot stop this so
  655.   all your virtual /dev/log's will now function.  Note that all the
  656.   messages from all the environments will be logged in one place.
  657.   However, you can write separate programs to filter out the data.  If
  658.   you do not want to write a program and require separate log files you
  659.   can use a separate syslog for each virtual filesystem by running:
  660.  
  661.   syslog -p /virtual/domain1.com/dev/log
  662.   syslog -p /virtual/domain2.com/dev/log
  663.  
  664.   However that wastes process id's so I do not recommend it.  This
  665.   version of the syslog.init file relinks the /dev/log's each time you
  666.   start it in case they have been improperly set up.  Here is a modified
  667.   syslog.init file:
  668.  
  669.   #!/bin/sh
  670.  
  671.   # Source function library.
  672.   \&. /etc/rc.d/init.d/functions
  673.  
  674.   case "$1" in
  675.     start)
  676.           echo -n "Starting dev log: "
  677.           ln -sf /virtual/log /dev/log
  678.           echo done
  679.           echo -n "Starting system loggers: "
  680.           daemon syslogd -p /virtual/log
  681.           daemon klogd
  682.           echo
  683.           echo -n "Starting virtual dev log: "
  684.           for i in /virtual/*
  685.           do
  686.                   if [ ! -d "$i" ]
  687.                   then
  688.                           continue
  689.                   fi
  690.                   if [ "$i" = "/virtual/lost+found" ]
  691.                   then
  692.                           continue
  693.                   fi
  694.                   ln -f /virtual/log $i/dev/log
  695.                   echo -n "."
  696.           done
  697.           echo " done"
  698.           touch /var/lock/subsys/syslog
  699.           ;;
  700.     stop)
  701.           echo -n "Shutting down system loggers: "
  702.           killproc syslogd
  703.           killproc klogd
  704.           echo
  705.           rm -f /var/lock/subsys/syslog
  706.           ;;
  707.     *)
  708.           echo "Usage: syslog {start|stop}"
  709.           exit 1
  710.   esac
  711.  
  712.   exit 0
  713.  
  714.   Note that you do not have to put all the virtual filesystems on one
  715.   disk.  However, you will have to run a different syslog for each
  716.   partition that has virtual filesystems on it.
  717.  
  718.   7.  Virtual FTP
  719.  
  720.   Wu-ftpd comes with built in support to make it virtual.  However, you
  721.   cannot maintain separate password files for each domain.  For example,
  722.   if
  723.    bob@domain1.com  and  bob@domain2.com  both want an account you would
  724.   have to make one of them bob2 or have one of the users choose a
  725.   different user name.  Since you now have a virtual filesystem for each
  726.   domain you have separate password files and this problem goes away.
  727.   Just create a virtnewuser script and virtpasswd script in the way
  728.   mentioned above and you are all set.  You can also have anonymous ftp
  729.   in each virtual environment as that would be unaffected by the virtual
  730.   filesystem as well.
  731.  
  732.   The inetd.conf entries for wu-ftp:
  733.  
  734.   ftp stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.ftp wu.ftpd -l -a
  735.  
  736.   8.  Virtual Web
  737.  
  738.   Apache has their own support for virtual domains.  This is the only
  739.   program I recommend using the internal virtual domain mechanism.
  740.   When you run something through inetd there is a cost.  The program now
  741.   has to start up each time you run it.  That means slower response
  742.   times which is unacceptable for web service.  Apache also has a
  743.   mechanism for stopping connections when too many come in.
  744.  
  745.   However, if you did want to run Apache through inetd then add the
  746.   following line to your inetd.conf file:
  747.  
  748.   www stream tcp nowait www /usr/bin/virtuald virtuald /virtual/conf.www httpd -f /var/www/conf/httpd.conf
  749.  
  750.   In the /var/www/conf/httpd.conf file you have to specify:
  751.  
  752.   ServerType inetd
  753.  
  754.   Then configure each instance of the Apache server like you would
  755.   normally for single domain use.
  756.  
  757.   At the time of this writing there is no virtual web HOWTO.  However, I
  758.   am under the impression one is coming.  Eventually I will just refer
  759.   to that HOWTO and have some notes on it.  If it does not come soon and
  760.   I get enough requests I will write a small section on how to configure
  761.   the Apache virthost directive.
  762.  
  763.   9.  Virtual Mail/Pop
  764.  
  765.   9.1.  Qmail Notice
  766.  
  767.   This section applies to sendmail only.  A section for qmail will be
  768.   added in the next version of this HOWTO document.
  769.   9.2.  Problem
  770.  
  771.   Virtual mail support is in ever increasing demand.  Sendmail says it
  772.   supports virtual mail.  What it does support is listening for incoming
  773.   mail from different domains.  You can then specify to have the mail
  774.   forwarded somewhere.  However, if you forward it to the local machine
  775.   and have incoming mail to bob@domain1.com and bob@domain2.com they
  776.   will go to the same mail folder.  This is a problem since both bob's
  777.   are different people with different mail.
  778.  
  779.   9.3.  Bad Solution
  780.  
  781.   You can make sure that each user name is unique by using a numbering
  782.   scheme: bob1, bob2, etc or prepending a few characters to each
  783.   username dom1bob, dom2bob, etc.  You could also hack mail and pop to
  784.   do these conversions behind the scenes but that can get messy.
  785.   Outgoing mail also has the banner maindomain.com and you want each
  786.   subdomain's outgoing mail banner to be different.
  787.  
  788.   9.4.  Good Solution
  789.  
  790.   Each virtual filesystem gives a domain its own /etc/passwd.  This
  791.   means that bob@domain1.com and bob@domain2.com are different users in
  792.   different /etc/passwds so mail will be no problem.  They also have
  793.   their own spool directories so the mail folders will be different
  794.   files on different virtual filesystems.
  795.  
  796.   However, sendmail requires one minor source code modification.
  797.   Sendmail has a file called /etc/sendmail.cw and it contains all
  798.   machine names that sendmail will deliver mail to locally rather than
  799.   forwarding to another machine.  Sendmail does internal checking of all
  800.   the devices on the machine to initialize this list with the local IPs.
  801.   This presents a problem if you are mailing between virtual domains on
  802.   the same machine.  Sendmail will be fooled into thinking another
  803.   virtual domain is a local address and spool the mail locally.  For
  804.   example, bob@domain1.com sends mail to fred@domain2.com.  Since
  805.   domain1.com's sendmail thinks domain2.com is local, it will spool the
  806.   mail on domain1.com and never send it to domain2.com.  You have to
  807.   modify sendmail (I did this on v8.8.5 without a problem):
  808.  
  809.   vi v8.8.5/src/main.c # Approximately Line 494
  810.   It should say:
  811.  
  812.   load_if_names();
  813.  
  814.   Replace it with:
  815.  
  816.   /* load_if_names(); Commented out since hurts virtual */
  817.  
  818.   Note only do this if you need to send mail between virtual domains
  819.   which I think is probable.
  820.  
  821.   This will fix the problem.  However, the main ethernet device eth0 is
  822.   not removed.  Therefore, if you send mail from a virtual IP to the one
  823.   on eth0 on the same box it will delivery locally.  Therefore, I just
  824.   use this as a dummy IP virtual1.domain.com (10.10.10.157).  I never
  825.   send mail to this host so neither will the virtual domains.  This is
  826.   also the IP I would use to ssh into the box to check if the system is
  827.   ok.
  828.   Edit /etc/sendmail.cw with the local hostnames.
  829.  
  830.   vi /etc/sendmail.cw
  831.   mail.domain1.com
  832.   domain1.com
  833.   domain1
  834.   localhost
  835.  
  836.   Create /etc/sendmail.cf like you would normally through m4.  I used:
  837.  
  838.   divert(0)dnl
  839.   VERSIONID(`@(#)tcpproto.mc      8.5 (Berkeley) 3/23/96')
  840.   OSTYPE(linux)
  841.   FEATURE(redirect)
  842.   FEATURE(always_add_domain)
  843.   FEATURE(use_cw_file)
  844.   FEATURE(local_procmail)
  845.   MAILER(local)
  846.   MAILER(smtp)
  847.  
  848.   Edit /etc/sendmail.cf to respond as your virtual domain:
  849.  
  850.   vi /etc/sendmail.cf # Approximately Line 86
  851.   It should say:
  852.  
  853.   #Dj$w.Foo.COM
  854.  
  855.   Replace it with:
  856.  
  857.   Djdomain1.com
  858.  
  859.   Sendmail cannot be started stand alone anymore so you have to run it
  860.   through inetd.  This is inefficient and will result in lower start up
  861.   time but if you had such a high hit site you would not share it on a
  862.   virtual box with other domains.  Note that you are NOT running with
  863.   the  -bd  flag.  Also note that you need a  sendmail -q  running for
  864.   each domain to queue up undelivered mail. The new sendmail.init file:
  865.  
  866.   #!/bin/sh
  867.  
  868.   # Source function library.
  869.   \&. /etc/rc.d/init.d/functions
  870.  
  871.   case "$1" in
  872.     start)
  873.           echo -n "Starting sendmail: "
  874.           daemon sendmail -q1h
  875.           echo
  876.           echo -n "Starting virtual sendmail: "
  877.           for i in /virtual/*
  878.           do
  879.                   if [ ! -d "$i" ]
  880.                   then
  881.                           continue
  882.                   fi
  883.                   if [ "$i" = "/virtual/lost+found" ]
  884.                   then
  885.                           continue
  886.                   fi
  887.                   chroot $i sendmail -q1h
  888.                   echo -n "."
  889.           done
  890.           echo " done"
  891.           touch /var/lock/subsys/sendmail
  892.           ;;
  893.     stop)
  894.           echo -n "Stopping sendmail: "
  895.           killproc sendmail
  896.           echo
  897.           rm -f /var/lock/subsys/sendmail
  898.           ;;
  899.     *)
  900.           echo "Usage: sendmail {start|stop}"
  901.           exit 1
  902.   esac
  903.  
  904.   exit 0
  905.  
  906.   Pop should install normally with no extra effort.  It will just need
  907.   the inetd entry for it with the virtuald part added.  The inetd.conf
  908.   entries for sendmail and pop:
  909.  
  910.   pop-3 stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.pop in.qpop -s
  911.   smtp stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.mail sendmail -bs
  912.  
  913.   10.  Virtual other
  914.  
  915.   Any other service should be a similar procedure.
  916.  
  917.   ╖  Add the binary and the libraries to the virtual filesystem.
  918.  
  919.   ╖  Add it to /etc/inetd.conf.
  920.  
  921.   ╖  Create a /virtual/conf.service file.
  922.  
  923.   ╖  Create any virtual scripts that need to be made.
  924.  
  925.   I have experimented with both the samba package and have written a
  926.   virtual poppassd through Eudora.  Both work without any problems.  If
  927.   there is enough interest, I will add a section on installing virtual
  928.   samba.
  929.  
  930.   11.  Conclusion
  931.  
  932.   Those are all the steps you need.  I hope that this article meets with
  933.   a positive response.  Again mail any responses to Computer Resource
  934.   Center.  If you have a question or an update to the document let me
  935.   know and I will add it.
  936.  
  937.   12.  FAQ
  938.  
  939.   Q1. Why are there no questions in this FAQ?
  940.  
  941.   A1. Because nobody has asked any yet.
  942.  
  943.